import { Catch, HttpException, ExceptionFilter, ArgumentsHost } from '@nestjs/common';
import { Request, Response } from 'express';

// @Catch() 装饰器：声明此过滤器只处理 HttpException 类型的异常
// 当控制器/服务抛出 HttpException（或子类，如 NotFoundException）时，会被此过滤器捕获
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
	// ExceptionFilter 接口要求实现 catch() 方法
	// 参数说明：
	// - exception: 抛出的 HttpException 实例，可获取状态码、提示信息等
	// - host: ArgumentsHost，Nest 提供的“执行上下文”，可转换成不同平台的请求上下文（HTTP、WebSocket 等）
	catch(exception: HttpException, host: ArgumentsHost) {
		const ctx = host.switchToHttp();
		const response = ctx.getResponse<Response>();
		const request = ctx.getRequest<Request>();
		const status = exception.getStatus();

		// ① 拿到原始错误详情 —— 可能是字符串，也可能是对象（比如 ValidationPipe 的 message 数组）
		const rawError = exception.getResponse();

		// ② 统一整理出 message / errors 字段，方便前端 使用
		let message: string | string[] = '服务内部错误';
		let errors: Record<string, unknown> | undefined;

		if (typeof rawError === 'string') {
			message = rawError;
		} else if (typeof rawError === 'object' && rawError) {
			// Nest/ValidationPipe 默认返回 { statusCode, message, error }
			// DTO 校验失败时 message 通常是字符串数组
			const { message: msg, ...rest } = rawError as { message?: unknown } & Record<string, unknown>;
			if (typeof msg === 'string') {
				message = msg;
			} else if (
				Array.isArray(msg) &&
				msg.every((item): item is string => typeof item === 'string')
			) {
				message = msg;
			} else if (msg !== undefined && msg !== null) {
				message = String(msg as unknown);
			}
			errors = Object.keys(rest).length > 0 ? rest : undefined;
		}

		const errorResponse = {
			statusCode: status,
			timestamp: new Date().toISOString(),
			path: request.url,
			method: request.method,
			message, // 统一的错误提示
			errors, // 额外错误信息（可选，例如 error: 'Bad Request' 或详细字段错误）
		};

		console.log('🚨 捕获到 HTTP 异常:', errorResponse);
		response.status(status).json(errorResponse);
	}
}
